package com.irdstudio.apicenter.core.code.generator.veloctity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.lang.Validate;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.irdstudio.apicenter.core.code.generator.ICodeGenerator;

/**
 * 基于Velocity 模板的代码生成器
 * 
 * @author ZhangHao
 * @date 2015-6-21
 * @version 1.0
 * 
 */
public abstract class VelocityCodeGenerator implements ICodeGenerator {

	protected final static Logger logger = LoggerFactory
			.getLogger(VelocityCodeGenerator.class);
	private static final String velocityfile = "/Users/ZhangHao/Documents/workspace/macms/src/main/java/com/yuchengtech/core/code/generator/veloctity/html/velocityParams.properties";
	private static Map<String, String> velocityParams = null;
	private static PropertiesConfiguration configuration = null;
	protected VelocityContext context = new VelocityContext();

	public VelocityCodeGenerator() {

		Velocity.init(velocityfile);

	}

	public void generator(Object data) throws Exception {

		Validate.isTrue(data instanceof VelocityTempletData,
				"ClassCastException VelocityTempletData.");

		VelocityTempletData templetData = (VelocityTempletData) data;

		final String templetFile = templetData.getTempletFile();
		final String tFilePach = templetData.gettFilePach();
		final String tFileName = templetData.getTfileName();
		List<?> tempData = templetData.getTempletData();

		FileOutputStream fo = null;
		try {

			Validate.notEmpty(templetFile, " tFilePach is empty.");

			Template template = Velocity.getTemplate(templetFile);
			Validate.notNull(template, templetFile + " not found.");

			constructionTemplet(tempData);

			StringWriter stringWriter = new StringWriter();
			template.merge(context, stringWriter);

			String content = stringWriter.toString();
			logger.debug(content);

			File directory = new File(tFilePach);
			Validate.isTrue(directory.exists() && directory.isDirectory(),
					"directory ： " + tFilePach + " not found.");

			String fileName = tFilePach + tFileName;
			File f = new File(fileName);

			if (!f.exists()) {
				f.createNewFile();
				logger.info(fileName + " is added.");
			} else
				logger.info(fileName + " is overwrited.");

			fo = new FileOutputStream(f);
			fo.write(content.getBytes(velocityParams.get("output.encoding")));

		} catch (Exception e) {
			logger.error(" error", e);
			throw e;
		} finally {
			try {
				if (fo != null)
					fo.close();
			} catch (Exception e2) {
				logger.error("OutputStream close FAILED.", e2);
			}
		}
	}

	protected abstract void constructionTemplet(List<?> tempData)
			throws Exception;

	static {
		try {

			logger.info("init velocityParams.properties...");
			configuration = new PropertiesConfiguration(velocityfile);
			velocityParams = new HashMap<String, String>();

			Iterator<String> keys = configuration.getKeys();
			while (keys.hasNext()) {
				String key = keys.next();
				String value = configuration.getString(key);
				velocityParams.put(key, value);
				logger.info("key = " + key + " value = " + value);
			}
		} catch (ConfigurationException e) {
			velocityParams = null;
			logger.error("velocityParams.properties init error : ", e);
		}
	}

}
